package org.ghost.spring.cloud.consumer.demo.config;

import org.apache.commons.lang3.ArrayUtils;
import org.ghost.spring.cloud.consumer.demo.util.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class TaskExecutorConfig implements AsyncConfigurer {
    private final static Logger logger = LoggerFactory.getLogger(TaskExecutorConfig.class);

    private enum Singleton {
        INSTANCE;

        private ThreadPoolTaskExecutor taskExecutor = null;

        Singleton() {
            taskExecutor = new ThreadPoolTaskExecutor();
            taskExecutor.setCorePoolSize(5);
            taskExecutor.setMaxPoolSize(20);
            taskExecutor.setQueueCapacity(2000);
            taskExecutor.setThreadNamePrefix("TEST_");
            taskExecutor.initialize();
        }

        public ThreadPoolTaskExecutor getInstance() {
            return taskExecutor;
        }
    }


    public AsyncTaskExecutor getAsyncTaskExecutor() {
        return Singleton.INSTANCE.getInstance();
    }


    @Override
    public Executor getAsyncExecutor() {
        return Singleton.INSTANCE.getInstance();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> logger.error("*****AsyncUncaughtExceptionHandler:方法:{},参数:{},错误:{}", method.getDeclaringClass().getName() + "." + method.getName(), getParams(params), ExceptionUtil.getExceptionStack(ex));
    }

    private String getParams(Object... params) {
        if (ArrayUtils.isNotEmpty(params)) {
            StringBuilder builder = new StringBuilder();
            int len = params.length;
            for (int i = 0; i < len; i++) {
                builder.append(";para").append(i).append("->").append(params[i]);
            }
            return builder.toString();
        }
        return null;
    }
}
